﻿namespace BrowserCacheBustingUtilities
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Xml;

    internal class VersionManager
    {

        private const string VersionNumberSuffix = "_v";
        private static XmlDocument VersionFile;
        internal static bool Loaded;

        public static string VersionFilePath { get; set; }

        public static void Save()
        {
            LoadFileVersions();
            VersionFile.Save(VersionFilePath);
        }

        public static void AddFileVersion(FileVersion fileVersion)
        {
            LoadFileVersions();
            XmlElement root = VersionFile.DocumentElement;

            XmlElement element = VersionFile.CreateElement("file");

            XmlAttribute attribute = VersionFile.CreateAttribute("id");
            attribute.Value = fileVersion.Id.ToString();
            element.Attributes.Append(attribute);

            attribute = VersionFile.CreateAttribute("filePath");
            attribute.Value = fileVersion.FilePath.ToLower().Trim();
            element.Attributes.Append(attribute);

            attribute = VersionFile.CreateAttribute("versionNumber");
            attribute.Value = fileVersion.VersionNumber.ToString();
            element.Attributes.Append(attribute);

            attribute = VersionFile.CreateAttribute("hash");
            attribute.Value = fileVersion.Hash;
            element.Attributes.Append(attribute);

            root.AppendChild(element);
        }

        public static void UpdateFileVersion(FileVersion fileVersion)
        {
            XmlNode element = VersionFile.SelectSingleNode(string.Format("//file[@id='{0}']", fileVersion.Id.ToString()));

            if (element == null)
            {
                AddFileVersion(fileVersion);
                return;
            }

            element.Attributes["versionNumber"].Value = fileVersion.VersionNumber.ToString();
            element.Attributes["hash"].Value = fileVersion.Hash;
        }

        public static FileVersion FindFileVersion(string filePath)
        {
            LoadFileVersions();
            XmlNode element = VersionFile.SelectSingleNode(string.Format("//file[@filePath='{0}']", filePath.ToLower().Trim()));

            if (element != null)
            {
                return new FileVersion
                    {
                        Id = Guid.Parse(element.Attributes["id"].Value),
                        FilePath = element.Attributes["filePath"].Value,
                        VersionNumber = int.Parse(element.Attributes["versionNumber"].Value),
                        Hash = element.Attributes["hash"].Value
                    };
            }

            return null;
        }

        public static int? GetFileVersionNumber(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath))
                return null;

            string fileName = filePath.Substring(filePath.LastIndexOf(@"\") + 1);

            if (fileName.Contains("."))
                fileName = fileName.Substring(0, fileName.LastIndexOf("."));

            int index = fileName.IndexOf(VersionNumberSuffix, StringComparison.CurrentCultureIgnoreCase);

            if (index != -1)
            {
                string versionNumber = fileName.Substring(fileName.IndexOf(VersionNumberSuffix) + VersionNumberSuffix.Length);

                int parsedVersionNumber = 0;

                if (int.TryParse(versionNumber, out parsedVersionNumber) && parsedVersionNumber > 0)
                    return parsedVersionNumber;
            }

            return null;
        }

        public static string GetFilePathWithoutVersionNumber(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath))
                return string.Empty;

            string path = filePath.Substring(0, filePath.LastIndexOf(@"\") + 1);
            string fileName = filePath.Substring(filePath.LastIndexOf(@"\") + 1);
            string extension = string.Empty;

            if (fileName.Contains("."))
            {
                extension = fileName.Substring(fileName.IndexOf("."));
                fileName = fileName.Substring(0, fileName.LastIndexOf("."));
            }

            int index = fileName.IndexOf(VersionNumberSuffix, StringComparison.CurrentCultureIgnoreCase);

            if (index != -1)
                fileName = fileName.Substring(0, index);

            return string.Concat(path, fileName, extension);
        }

        public static string GetFilePathWithVersionNumber(string filePath, int versionNumber)
        {
            if (string.IsNullOrWhiteSpace(filePath))
                return string.Empty;

            string path = filePath.Substring(0, filePath.LastIndexOf(@"\") + 1);
            string fileName = filePath.Substring(filePath.LastIndexOf(@"\") + 1);
            string extension = string.Empty;

            if (fileName.Contains("."))
            {
                extension = fileName.Substring(fileName.IndexOf("."));
                fileName = fileName.Substring(0, fileName.LastIndexOf("."));
            }

            int index = fileName.IndexOf(VersionNumberSuffix, StringComparison.CurrentCultureIgnoreCase);

            if (index != -1)
                fileName = fileName.Substring(0, index);

            fileName += string.Concat(VersionNumberSuffix, versionNumber);

            return string.Concat(path, fileName, extension);
        }

        private static void LoadFileVersions()
        {
            if (Loaded)
                return;

            Loaded = true;

            if (File.Exists(VersionFilePath))
            {
                VersionFile = new XmlDocument();
                VersionFile.Load(VersionFilePath);
                return;
            }

            VersionFile = new XmlDocument();

            XmlElement root = VersionFile.CreateElement("versions");
            VersionFile.AppendChild(root);

            VersionFile.Save(VersionFilePath);
        }
    }
}
